#ifndef CALCU_H_INCLUDED
#include "calcu.h"
using namespace std;

//找到最近的换乘点
void find_nearest_cross(int start_or_end, int station_number, array<int, 4>& near_station, array<int, 4>& near_distance)
{   //首先遍历每条线路，找到输入的站点编号，显然单条地铁线路是无环的，分支会分成两条重叠的记录
    for (int j = 0;j < 5;j++){
        for (list<station>::iterator it = line_list[j].begin();it != line_list[j].end();it++){
            if (it->_number == station_number){
                //向前搜索
                list<station>::iterator it_f = it;
                while (it_f != line_list[j].end()){
                    if (it_f->_is_cross == 1){
                        for (int k = 0;k < cross_number; k++){
                            if (cross[k] == it_f->_number){
                                near_station.at(start_or_end) = k;
                                break;
                            }
                        }
                        break;
                    } else {
                        near_distance.at(start_or_end)++;
                        it_f++;
                    }
                }
                //向后搜索
                list<station>::iterator it_b = it;
                while (it_b != line_list[j].begin()){
                    if (it_b->_is_cross == 1){
                        for (int k = 0;k < cross_number; k++){
                            if (cross[k] == it_b->_number) {
                                near_station.at(start_or_end + 1) = k;
                                break;
                            }
                        }
                        break;
                    } else {
                        near_distance.at(start_or_end + 1)++;
                        it_b--;
                    }
                }
                //单独处理遍历到line[j].begin()的情况，因为我用reverse iterator怎么也写不对
                if(it_b == line_list[j].begin() && it_b->_is_cross == 1){
                    for (int k = 0;k < cross_number; k++){
                        if (cross[k] == it_b->_number) {
                            near_station.at(start_or_end + 1) = k;
                            break;
                        }
                    }
                }
                //假如两个最近换乘点都找到了，则提前跳出循环
                if (near_station.at(start_or_end) != INT_MIN && near_station.at(start_or_end + 1) != INT_MIN){
                    return;
                }
            }
        }
    }
}
//计算最短路线的段数
int arrange_route(int start_station, int end_station)
{
    const int is_start = 0; //注：偏移量比较少就不用enum了
    const int is_end = 2;   //注：终点最近换乘站的数组偏移量，不想开两个数组
    //存最近换乘站的编号和起/终点距离最近换乘站的距离，反正也就用到一次用不着划分内存池
    array<int, 4> near_cross;
    near_cross.fill(INT_MIN);
    array<int, 4>cross_dist;
    cross_dist.fill(INT_MAX);

    //首先查询这个站点是不是换乘点，如果是就把第一个最近换乘点标记为它本身，第二个保持负无穷
    for (int i = 0;i < cross_number;i++){
        near_cross.at(is_start) = (start_station == cross[i]) ? i : INT_MIN;
        near_cross.at(is_end) = (end_station == cross[i]) ? i : INT_MIN;
    }
    //否则寻找它最近的换乘点
    if (near_cross.at(is_start) == INT_MIN){
        find_nearest_cross(is_start, start_station, near_cross, cross_dist);
    } else {
        cross_dist.at(is_start) = 0;
    }
    if (near_cross.at(is_end) == INT_MIN){
        find_nearest_cross(is_end, end_station, near_cross, cross_dist);
    } else {
        cross_dist.at(is_end) = 0;
    }

    //枚举4种情况，利用已经计算好的数据得到最短路线经过的段数，假如换乘点没找到就跳过这组枚举
    int min_sum_dist = INT_MAX;
    int temp_sum_dist = INT_MAX;
    for (int i = 0;i < 2;i++){
        for (int j = 2;j < 4;j++){
            if(near_cross.at(i) != INT_MIN && near_cross.at(j) != INT_MIN){
                temp_sum_dist = cross_dist.at(i) + cross_dist.at(j) + dist.at(near_cross.at(i) * 6 + near_cross.at(j));
                min_sum_dist = min(temp_sum_dist, min_sum_dist);
            }
        }
    }
    if (min_sum_dist == INT_MAX){
        cout << "貌似没能找到连通两个站点的路径\n";
        //假如地图不是全联通的，这会被设为第3种输入框报错，清除起点和终点的输入框，但是这个demo还没这么复杂
        //如果考虑这种情况，那么还要在最前面检测一个找是不是在同一线路上（处理“这条线路没有换乘点”的情况）
    }
    return min_sum_dist;
}

//计算价格
int calcu_price(int number)
{   //简单起见，假设每两个站之间距离相等为1个单位
    int res = 0;            //注：仅仅为了维持SISO结构，写main()的时候已经逐渐放弃了
    if (number <= 1){
        res = 4;
    } else if (number <= 4){ //注：因为用了else，所以左边界已经被排除了，不用多判断一次
        res = 2 * number;
    } else {
        res = number + 4;
    }
    return res;
}

//把金额折算为投币金额
cash cvrt_price_to_cash(int price)
{
    cash res = {0, 0, 0};
    res.number_10yuan = price / 10;
    price = price % 10;
    if (price >= 5){
        price -= 5;
        res.number_5yuan = 1;
    }
    res.number_1yuan = price;
    return res;
}
